'''
Created on Apr 22, 2013

@author: alex
'''
import socket, sys
from socket import *
from struct import *
import random

class CustomSocket:
    def __init__(self):
        self.HOST = gethostbyname(gethostname())    
        self.fromClient = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)    
        self.fromClient.bind(('127.0.0.1',8080))
    
    def listen(self):
        while 1:
            #Listening loop
            recPacket = self.fromClient.recvfrom(8192)
            #get packet string from tuple
            recPacket = recPacket[0]
            
            #IP Header            
            ipheader = recPacket[0:20]            
            iph = unpack('!BBHHHBBH4s4s', ipheader)
            source_ip = inet_ntoa(iph[8])
            dest_ip = inet_ntoa(iph[9])
            print 'Source ip: '+str(source_ip)+' Dest ip: '+str(dest_ip)            
            
            #TCP Header
            tcpheader = recPacket[20:40]
            tcpheader = unpack('!HHLLBBHHH', tcpheader)
            source_port = tcpheader[0]
            dest_port = tcpheader[1]
            seq = tcpheader[2]
            ack = tcpheader[3]
            tcp_length = (tcpheader[4] >> 4)
            print 'Source port: '+str(source_port)+' Dest port: '+str(dest_port)+ ' seq: '+str(seq)+ ' ack: '+str(ack)+' tcplength: '+str(tcp_length)
            
            #Build SYN response
            # ip header fields
            ihl = 5
            version = 4
            tos = 0
            tot_len = 20 + 20   # python seems to correctly fill the total length, dont know how ??
            id = 54321  #Id of this packet
            frag_off = 0
            ttl = 255
            protocol = socket.IPPROTO_TCP
            check = 10  # python seems to correctly fill the checksum
            saddr = socket.inet_aton ( self.HOST )
            daddr = socket.inet_aton ( source_ip )
             
            ihl_version = (version << 4) + ihl
            
            syn_ip_header = pack('!BBHHHBBH4s4s' , ihl_version, tos, tot_len, id, frag_off, ttl, protocol, check, saddr, daddr)
            
            sequence = random.randint(0, 65586)
            ack = ack+1
            doff = 5
            #TCP Flags
            fin = 0
            syn = 1
            rst = 0
            psh = 0
            ac = 0
            urg = 0
            window = htons (5840)
            check = 0
            urg_ptr = 0
 
            offset_res = (doff << 4) + 0
            tcp_flags = fin + (syn << 1) + (rst << 2) + (psh <<3) + (ac << 4) + (urg << 5)
            syn_tcp_header = pack('!HHLLBBHHH' , dest_port, source_port, sequence, ack, offset_res, tcp_flags,  window, check, urg_ptr)
            
            syn_packet = syn_ip_header + syn_tcp_header
            
            self.fromClient.sendto(syn_packet, (daddr, 0))

if __name__ == '__main__':
    s = CustomSocket()
    s.listen()